/*
 * 描          述:  <描述>
 * 修  改   人:  PengQingyang
 * 修改时间:  2013-8-19
 * <修改描述:>
 */
package com.tx.core.starter.component;

import com.baomidou.mybatisplus.annotation.DbType;
import com.tx.core.ddlutil.dialect.Dialect4DDL;
import com.tx.core.ddlutil.dialect.impl.H2DDLDialect;
import com.tx.core.ddlutil.dialect.impl.MySQLDDLDialect;
import com.tx.core.ddlutil.dialect.impl.PostgreSQLDDLDialect;
import com.tx.core.exceptions.SILException;
import com.tx.core.exceptions.util.AssertUtils;
import org.hibernate.dialect.*;

import java.lang.reflect.InvocationTargetException;

/**
 * 数据库类型<br/>
 * <功能详细描述>
 *
 * @author PengQingyang
 * @version [版本号, 2013-8-19]
 * @see [相关类/方法]
 * @since [产品/模块版本]
 */
public enum DatabaseTypeEnum {

    /** H2 */
    H2("H2", H2Dialect.class, H2Dialect.class.getName(), H2DDLDialect.INSTANCE, DbType.H2),

    /** MYSQL */
    MySQL("MySQL", MySQLDialect.class, MySQL57Dialect.class.getName(), MySQLDDLDialect.INSTANCE, DbType.MYSQL),

    /** MYSQL */
    PostgreSQL("PostgreSQL", PostgreSQL81Dialect.class, PostgreSQL10Dialect.class.getName(),
            PostgreSQLDDLDialect.INSTANCE, DbType.POSTGRE_SQL);

    /** 数据源类型名 */
    private final String name;

    /** 对应hibernate方言 */
    private Dialect dialect;

    /** 默认的方言类类名 */
    private final String defaultDialectClassName;

    /** 方言类的基类 */
    private Class<? extends Dialect> dialectParentClazz;

    /** ddl生成方言 */
    private final Dialect4DDL dialect4DDL;

    private final DbType dbType;

    /** <默认构造函数> */
    private DatabaseTypeEnum(String name, Class<? extends Dialect> dialectParentClazz, String defaultDialectClassName,
                             Dialect4DDL dialect4DDL, DbType dbType) {
        this.name = name;
        this.dialectParentClazz = dialectParentClazz;
        this.defaultDialectClassName = defaultDialectClassName;
        this.dialect4DDL = dialect4DDL;
        this.dbType = dbType;
    }

    /**
     * @return 返回 name
     */
    public String getName() {
        return name;
    }

    /**
     * @return 返回 dialect
     */
    public Dialect getDialect() {
        if (this.dialect == null) {
            try {
                this.dialect =
                        (Dialect) Class.forName(this.defaultDialectClassName).getDeclaredConstructor().newInstance();
            } catch (InstantiationException | IllegalAccessException | InvocationTargetException |
                     NoSuchMethodException | ClassNotFoundException e) {
                throw new SILException("初始化默认的Diaclect实例异常.", e);
            }
        }
        return dialect;
    }

    /**
     * @return 返回 dialect4DDL
     */
    public Dialect4DDL getDialect4DDL() {
        return dialect4DDL;
    }

    /**
     * 设置方言类<br/>
     *
     * @param dialect
     */
    void setDialect(Dialect dialect) {
        AssertUtils.notNull(dialect, "dialect is null.");
        AssertUtils.isTrue(this.dialectParentClazz.isInstance(dialect), "dialect should is instance of:{}, fact " +
                "is:{}", new Object[]{this.dialectParentClazz, dialect});

        this.dialect = dialect;
    }

    /**
     * @return
     */
    public DbType getDbType() {
        return dbType;
    }
}
